package com.xjc.system.websocket.handler;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.xjc.business.entity.domain.ChatMsg;
import com.xjc.business.entity.domain.SysMsg;
import com.xjc.business.entity.po.ChatMsgPo;
import com.xjc.business.entity.vo.classadmin.ChatMsgContainer;
import com.xjc.business.service.*;
import com.xjc.system.constants.MyConstants;
import com.xjc.system.utils.MailUtil;
import com.xjc.system.websocket.relation.UserChanelRel;
import com.xjc.system.websocket.entity.MsgActionEnum;
import com.xjc.system.utils.SpringBeanContext;
import com.xjc.system.websocket.entity.DataContent;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.*;

/**
 * 用于处理消息的handler
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //用于记录和管理所有客户端的channel
    public static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

        //获取消息service对象
        ChatMsgService chatMsgService = SpringBeanContext.getContext().getBean(ChatMsgService.class);

        ClassAdminsService classAdminsService = SpringBeanContext.getContext().getBean(ClassAdminsService.class);

        StudentsService studentsService = SpringBeanContext.getContext().getBean(StudentsService.class);

        WxUserService wxUserService = SpringBeanContext.getContext().getBean(WxUserService.class);


        MailUtil mailUtil = SpringBeanContext.getContext().getBean(MailUtil.class);

        //1.获取客户端发来的消息
        String content = msg.text();

        //消息
        Map dataContent = (Map) JSONUtils.parse(content);

        //类型
        Integer action = (Integer) dataContent.get("action");

        Map chatMsgPo = (Map)dataContent.get("chatMsgPo");

        Channel channel = ctx.channel();

        //2.判断消息类型，根据不同的类型来处理不同的业务
        if (action == MsgActionEnum.CONNECT.type) {//连接

            System.out.println("客户端:" + ctx.channel().id().asLongText() + ",发来连接消息");

            //发送者id
            String sendId = String.valueOf(chatMsgPo.get("sendId"));
            //绑定
            UserChanelRel.manage.put(sendId, channel);

            UserChanelRel.output();

        } else if (action == MsgActionEnum.CHAT.type) {//聊天

            System.out.println("客户端:" + ctx.channel().id().asLongText() + ",发来聊天消息");

            //保持消息到数据库
            String sendId = String.valueOf(chatMsgPo.get("sendId"));
            String reviceId = String.valueOf(chatMsgPo.get("reviceId"));
            String msg1 = String.valueOf(chatMsgPo.get("msg"));
            String pic = String.valueOf(chatMsgPo.get("pic"));
            String video = String.valueOf(chatMsgPo.get("video"));
            String file = String.valueOf(chatMsgPo.get("file"));
            String icon = String.valueOf(chatMsgPo.get("icon"));
            Integer type = (Integer) chatMsgPo.get("type");
            String sessionId = String.valueOf(chatMsgPo.get("sessionId"));

            ChatMsg chatMsg = new ChatMsg();
            chatMsg.setSendId(sendId);
            chatMsg.setReviceId(reviceId);
            chatMsg.setReadStatus(MyConstants.MSG_NOT_READ);
            chatMsg.setMsg(msg1);
            chatMsg.setPic(pic);
            chatMsg.setFile(file);
            chatMsg.setVideo(video);
            chatMsg.setIcon(icon);
            chatMsg.setType(type);
            chatMsg.setSessionId(sessionId);
            chatMsg.setCreateTime(new Date());
            chatMsg.setUpdateTime(new Date());

            chatMsgService.save(chatMsg);

            //判断是否在线
            Channel receiverChannel = UserChanelRel.manage.get(reviceId);
            Channel channelInUsers = users.find(receiverChannel.id());
            UserChanelRel.output();

            //在线-发送
            if (receiverChannel != null && channelInUsers!=null) {

                // 单条消息封装
                ChatMsgPo msgPo = new ChatMsgPo();
                msgPo.setMsgId(chatMsg.getId());
                msgPo.setSendId(sendId);
                msgPo.setReviceId(reviceId);
                msgPo.setReadStatus(MyConstants.MSG_NOT_READ);
                msgPo.setMsg(msg1);
                msgPo.setPic(pic);
                msgPo.setFile(file);
                msgPo.setVideo(video);
                msgPo.setIcon(icon);
                msgPo.setType(type);
                msgPo.setSessionId(sessionId);
                msgPo.setCreateTime(chatMsg.getCreateTime());
                msgPo.setUpdateTime(new Date());

                // 辅导员发给学生
                if(sendId.contains("classAdmin:")){
                    //非首次接入-发送单条消息
                    receiverChannel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(msgPo)));
                }else{
                    // 学生发给辅导员
                    Long num = chatMsgService.getMessageNumWithSessionId(sessionId);
                    // 首次接入-发送完整消息（封装ChatMsgContainer）
                    if(num==1){
                        ChatMsgContainer wholeMsg = chatMsgService.getWholeMsg(sendId.split(":")[1]);
                        wholeMsg.setUnReadNum(1);
                        wholeMsg.setUnReadMsgIdList(Collections.singletonList(chatMsg.getId()));
                        wholeMsg.setChatMsgList(Collections.singletonList(msgPo));
                        receiverChannel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(wholeMsg)));
                    }else{
                        // 非首次接入-发送单条消息
                        receiverChannel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(msgPo)));
                    }

                }

            }
            else{
                // 不在线
                String email = "";

                String id = reviceId.split(":")[1];
                if(sendId.contains("classAdmin:")){
                    Integer stuId = wxUserService.getById(id).getStuId();
                    email = studentsService.getById(stuId).getEmail();

                    // 辅导员发给学生
                    mailUtil.sendSimpleMail("1014691048@qq.com",email,"掌上宿舍通-心理之窗","收到一条辅导员的温馨回信，请登录查收");

                }else{
                    email = classAdminsService.getById(id).getEmail();

                    mailUtil.sendSimpleMail("1014691048@qq.com",email,"宿舍管理系统-心理之窗","收到一条学生的求助信息，请登录查收");
                }
                System.out.println("邮件通知"+email);
            }
        } else if (action == MsgActionEnum.SIGNED.type) {
            System.out.println("客户端:" + ctx.channel().id().asLongText() + ",发来签收消息");
            //签收
            List<Integer> msgIdList = (List<Integer>) dataContent.get("msgIdList");
            chatMsgService.updateMsgStatusById(msgIdList,MyConstants.MSG_HAS_READ );

        } else if (action == MsgActionEnum.KEEPALIVE.type){
            //12秒之内接收到客户端消息 则不会主动断开连接
            //消息内容任意 类型为心跳即可
            System.out.println("客户端:" + ctx.channel().id().asLongText() + ",发来心跳消息");
        }

        else {
            System.out.println("客户端:" + ctx.channel().id().asLongText() + ",发来其他消息");

        }
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        users.add(ctx.channel());
        System.out.println("客户端:" + ctx.channel().id().asLongText() + ",上线");
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        users.remove(ctx.channel());
        System.out.println("客户端:" + ctx.channel().id().asLongText() + ",下线");

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.channel().close();
        users.remove(ctx.channel());
    }
}
